#include "app_mqtt.h"

#define ADDRESS "tcp://192.168.50.131:1883"
#define CLIENTID "myClientSub"
#define UPLOAD_TOPIC "Upload"
#define DOWNLOAD_TOPIC "Download"
//#define PAYLOAD "Hello World!"
#define QOS 0
#define TIMEOUT 10000L

// 定义结构体存放客户端 与接收回调函数
typedef struct
{
    MQTTClient client;
    void (*recv_cv)(void *data, int len);
} app_mqtt_t;

static app_mqtt_t my_mqtt;

// 声明回调函数

/// @brief 连接丢失回调
/// @param context 你传入的上下文指针
/// @param cause 断开原因字符串
static void connectionLost_cb(void *context, char *cause);

/// @brief 消息到达回调
/// @param context 用户上下文
/// @param topicName 消息主题
/// @param topicLen 主题长度（通常可以忽略）
/// @param message 消息对象，包含 payload、payloadlen 等
/// @return 通常返回 1 表示消息已处理完成，返回 0 表示未处理
static int messageArrived_cb(void *context, char *topicName, int topicLen, MQTTClient_message *message);

/// @brief 消息发送完成回调
/// @param context 用户上下文
/// @param dt 消息的 delivery token，用于确认具体哪条消息已经送达
static void deliveryComplete_cb(void *context, MQTTClient_deliveryToken dt);



/// @brief MQTT初始化
/// @param
/// @return
Com_state_t app_mqtt_init(void)
{
    log_info("正在创建MQTTClient");

    // 如果客户端创建失败
    if (MQTTClient_create(&(my_mqtt.client),
                          ADDRESS,
                          CLIENTID,
                          MQTTCLIENT_PERSISTENCE_NONE,
                          NULL) != MQTTCLIENT_SUCCESS)
    {
        log_error("MQTT客户端创建失败");
        return Com_FAIL;
    }
    log_info("MQTT客户端创建成功");

    // 创建回调函数
    if (MQTTClient_setCallbacks(my_mqtt.client,
                                NULL,
                                connectionLost_cb,
                                messageArrived_cb,
                                deliveryComplete_cb) != MQTTCLIENT_SUCCESS)
    {
        log_error("MQTT回调函数创建失败");
        return Com_FAIL;
    }
    log_info("MQTT回调函数创建成功");

    // mqtt默认配置
    MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;

    // 连接MQTT服务器
    if (MQTTClient_connect(my_mqtt.client, &conn_opts) != MQTTCLIENT_SUCCESS)
    {
        log_error("MQTT连接失败");
        return Com_FAIL;
    }
    log_info("MQTT连接成功");

    // mqtt订阅
    if (MQTTClient_subscribe(my_mqtt.client, UPLOAD_TOPIC, QOS) != MQTTCLIENT_SUCCESS)
    {
        log_error("MQTT UPLOAD_TOPIC订阅失败");
    }
    log_info("MQTT UPLOAD_TOPIC订阅成功");

    if (MQTTClient_subscribe(my_mqtt.client, DOWNLOAD_TOPIC, QOS) != MQTTCLIENT_SUCCESS)
    {
        log_error("MQTT DOWNLOAD_TOPIC订阅失败");
    }
    log_info("MQTT DOWNLOAD_TOPIC订阅成功");

    return Com_OK;
}

/// @brief 停止MQTT客户端
/// @param
/// @return
Com_state_t app_mqtt_deinit(void)
{
    // 取消订阅
    if (MQTTClient_unsubscribe(my_mqtt.client, DOWNLOAD_TOPIC) != MQTTCLIENT_SUCCESS)
    {
        log_error("MQTT DOWNLOAD_TOPIC退订失败");
        return Com_FAIL;
    }
    log_info("MQTT DOWNLOAD_TOPIC退订成功");

    // 取消订阅
    if (MQTTClient_unsubscribe(my_mqtt.client, UPLOAD_TOPIC) != MQTTCLIENT_SUCCESS)
    {
        log_error("MQTT UPLOAD_TOPIC退订失败");
        return Com_FAIL;
    }
    log_info("MQTT UPLOAD_TOPIC退订成功");

    // 取消连接
    if (MQTTClient_disconnect(my_mqtt.client, TIMEOUT) != MQTTCLIENT_SUCCESS)
    {
        log_error("MQTT断开连接失败");
        return Com_FAIL;
    }
    log_info("MQTT断开连接成功");

    // 销毁客户端
    MQTTClient_destroy(&my_mqtt.client);
}

// 声明回调实现

/// @brief 连接丢失回调
/// @param context 你传入的上下文指针
/// @param cause 断开原因字符串
static void connectionLost_cb(void *context, char *cause)
{
    log_info("连接丢失 原因:%s", cause);

    // 断开连接就重新进行连接
    //  mqtt默认配置
    MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;

    while (1)
    {
        // 连接MQTT服务器
        if (MQTTClient_connect(my_mqtt.client, &conn_opts) != MQTTCLIENT_SUCCESS)
        {
            log_error("MQTT连接失败 3 秒后重试");
            sleep(3);
            continue;
        }
        log_info("MQTT重连成功");
        break;
    }

}

/// @brief 消息到达回调
/// @param context 用户上下文
/// @param topicName 消息主题
/// @param topicLen 主题长度（通常可以忽略）
/// @param message 消息对象，包含 payload、payloadlen 等
/// @return 通常返回 1 表示消息已处理完成，返回 0 表示未处理
static int messageArrived_cb(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    log_info("MQTT TopicName:%s\tmessage:%.*s",topicName,message->payloadlen,message->payload);

    my_mqtt.recv_cv(message->payload,message->payloadlen);

    return 1;
}

/// @brief 消息发送完成回调
/// @param context 用户上下文
/// @param dt 消息的 delivery token，用于确认具体哪条消息已经送达
static void deliveryComplete_cb(void *context, MQTTClient_deliveryToken dt)
{
    log_info("Message delivered: %d", dt);
}

/// @brief MQTT发送消息
/// @param data 
/// @param len 
/// @return 
Com_state_t app_mqtt_send(void *data, int len)
{
    if (MQTTClient_publish(my_mqtt.client, UPLOAD_TOPIC, len, data, 0, 0, NULL) != MQTTCLIENT_SUCCESS)
    {
        log_error("MQTT发布消息失败");
        return Com_FAIL;
    }
    log_info("MQTT发布消息成功");
    return Com_OK;
}



/// @brief 注册接收回调
/// @param recv_cv 
void app_mqtt_recv_callback_register(void (*recv_cv)(void *data, int len))
{
    my_mqtt.recv_cv = recv_cv;
    
    if (my_mqtt.recv_cv)
    {
        log_info("mqtt回调函数注册成功");
    }
    else
    {
        log_error("mqtt回调函数注册失败");
    }
    
}

